package cn.xinfei.xdecision.common.utils.util;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.CollectionUtils;

import java.beans.PropertyDescriptor;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * VO转换工具
 *
 * @author Zdy
 * @since 2023-03-16
 */
public class BeanUtilsPlus {

    private BeanUtilsPlus() {
    }

    /**
     * 列表元素类型转换
     *
     * @param sources  源类型的实例列表
     * @param supplier 目标类型构造器
     * @param <S>      源类型
     * @param <T>      目标类型
     * @return 具有目标类型的实例列表
     */
    public static <S, T> List<T> copyElements(Collection<S> sources, Supplier<T> supplier) {
        if (CollectionUtils.isEmpty(sources)) {
            return Collections.emptyList();
        }
        return sources.stream().map(x -> {
            T vo = supplier.get();
            org.springframework.beans.BeanUtils.copyProperties(x, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 类型转换
     *
     * @param source   源类型的实例
     * @param supplier 目标类型构造器
     * @param <S>      源类型
     * @param <T>      目标类型
     * @return 具有目标类型的实例
     */
    public static <S, T> T copyProperties(S source, Supplier<T> supplier) {
        if (Objects.isNull(source)) {
            throw new IllegalArgumentException("source can not be null");
        }
        T target = supplier.get();
        org.springframework.beans.BeanUtils.copyProperties(source, target);
        return target;
    }

    public static String[] getNullPropertyNames(Object source) {
        BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            // 此处判断可根据需求修改
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

}
